package device

import (
	"context"
	"fmt"
	"goAdapter/device/commInterface"
	"goAdapter/device/eventBus"
	"goAdapter/setting"
	"strconv"
	"time"

	lua "github.com/yuin/gopher-lua"
)

type CommunicationCmdTemplate struct {
	DevId      string //采集接口名称
	DeviceName string //采集接口下设备名称
	FunName    string
	FunPara    string
}

const (
	FunTypeGet int = 0
	FunTypeSet int = 1
)

type NodeCmdTemplate struct {
	FunType int
	node    *DeviceTSLPropertyTemplate
}

type CommunicationDirectDataReqTemplate struct {
	DevId string //采集接口名称
	Data  []byte
}

type CommunicationDirectDataAckTemplate struct {
	DevId  string //采集接口名称
	Status bool
	Data   []byte
}

type CommunicationMessageTemplate struct {
	SlaveName string `json:"DevId"`         //接口名称
	TimeStamp string `json:"TimeStamp"`     //时间戳
	Direction string `json:"DataDirection"` //数据方向
	Content   string `json:"DataContent"`   //数据内容
}

type CommunicationRxTemplate struct {
	Status bool
	RxBuf  []byte
}

type CommunicationManageTemplate struct {
	EmergencyRequestChan  chan CommunicationCmdTemplate
	EmergencyAckChan      chan CommunicationRxTemplate
	CommonRequestChan     chan CommunicationCmdTemplate
	CmdRequestChan        chan NodeCmdTemplate //命令通道
	DirectDataRequestChan chan CommunicationDirectDataReqTemplate
	DirectDataAckChan     chan CommunicationDirectDataAckTemplate
	PacketChan            chan []byte
	CommMessage           []CommunicationMessageTemplate
	QuitChan              chan bool
}

const (
	CommunicationManageMessageMaxCnt = 100
)

const (
	CommunicationState_Start int = iota
	CommunicationState_Generate
	CommunicationState_Send       //命令发送
	CommunicationState_Wait       //命令等待接收
	CommunicationState_WaitSucess //命令接收成功
	CommunicationState_WaitFail   //命令接收失败
	CommunicationState_Stop
	CommunicationState_DirectDataSend //透传数据发送
	CommunicationState_DirectDataWait //透传数据等待接收
	CommunicationState_DirectDataStop //透传数据任务停止
)

func NewCommunicationManageTemplate() *CommunicationManageTemplate {

	template := &CommunicationManageTemplate{
		EmergencyRequestChan:  make(chan CommunicationCmdTemplate, 1),
		CmdRequestChan:        make(chan NodeCmdTemplate),
		CommonRequestChan:     make(chan CommunicationCmdTemplate, 100),
		EmergencyAckChan:      make(chan CommunicationRxTemplate, 1),
		DirectDataRequestChan: make(chan CommunicationDirectDataReqTemplate, 1),
		DirectDataAckChan:     make(chan CommunicationDirectDataAckTemplate, 1),
		PacketChan:            make(chan []byte, 100), //最多连续接收100帧数据
		CommMessage:           make([]CommunicationMessageTemplate, 0),
		QuitChan:              make(chan bool, 2),
	}

	return template
}

func (c *CommunicationManageTemplate) CommunicationManageMessageAdd(slave string, dir string, buf []byte) {
	CommunicationMessage := CommunicationMessageTemplate{
		SlaveName: slave,
		TimeStamp: time.Now().Format("2006-01-02 15:04:05"),
		Direction: dir,
		Content:   fmt.Sprintf("%X", buf),
	}
	if len(c.CommMessage) < CommunicationManageMessageMaxCnt {
		c.CommMessage = append(c.CommMessage, CommunicationMessage)
	} else {
		c.CommMessage = c.CommMessage[1:]
		c.CommMessage = append(c.CommMessage, CommunicationMessage)
	}
}

func (c *CommunicationManageTemplate) CommunicationManageAddCommon(cmd CommunicationCmdTemplate) {

	c.CommonRequestChan <- cmd
}

func (c *CommunicationManageTemplate) CommunicationManageAddCmd(cmd NodeCmdTemplate) {
	c.CmdRequestChan <- cmd
}

func (c *CommunicationManageTemplate) CommunicationManageAddEmergency(cmd CommunicationCmdTemplate) CommunicationRxTemplate {

	c.EmergencyRequestChan <- cmd

	return <-c.EmergencyAckChan
}

func (c *CommunicationManageTemplate) CommunicationManageAddDirectData(req CommunicationDirectDataReqTemplate) CommunicationDirectDataAckTemplate {

	c.DirectDataRequestChan <- req

	return <-c.DirectDataAckChan
}

func (c *CommunicationManageTemplate) CommunicationManageProcessReceiveData(ctx context.Context, comm commInterface.CommunicationInterface) {

	//阻塞读
	rxBuf := make([]byte, 1024)
	rxBufCnt := 0

	setting.ZAPS.Debugf("通信接口[%s]接收数据协程1/4进入", comm.GetName())
	for {
		select {
		case <-ctx.Done():
			setting.ZAPS.Debugf("通信接口[%s]接收数据协程1/4退出", comm.GetName())
			return
		case <-c.QuitChan:
			setting.ZAPS.Debugf("通信接口[%s]接收数据协程1/4退出", comm.GetName())
			return
		default:
			//阻塞读
			rxBufCnt = comm.ReadData(rxBuf)
			if rxBufCnt > 0 {
				//setting.ZAPS.Debugf("%s:curRxBufCnt %v", slaveName, rxBufCnt)
				//setting.ZAPS.Debugf("%s:CurRxBuf %X", slaveName, rxBuf[:rxBufCnt])

				//追加接收的数据到接收缓冲区
				c.PacketChan <- rxBuf[:rxBufCnt]
				//清除本次接收数据
				rxBufCnt = 0
			}
			time.Sleep(10 * time.Millisecond)
		}
	}
}

func (c *CommunicationManageTemplate) CommunicationStateMachine(cmd CommunicationCmdTemplate,
	slaveName string,
	commInterface commInterface.CommunicationInterface,
	node *DeviceInfoTemplate,
	eventBus *eventBus.Bus,
	lStateMap map[string]*lua.LState,
	offLineCnt int) CommunicationRxTemplate {
	rxResult := CommunicationRxTemplate{
		Status: false,
	}

	//commState := CommunicationState_Start
	//
	//commStep := 0
	//txBuf := make([]byte, 0)
	//continues := false
	//startT := time.Now() //计算当前时间
	//func() {
	//	for {
	//		switch commState {
	//		case CommunicationState_Start:
	//			{
	//				commState = CommunicationState_Generate
	//			}
	//		case CommunicationState_Generate:
	//			{
	//				//--------------组包---------------------------
	//				result := false
	//				if cmd.FunName == "GetDeviceRealVariables" {
	//					txBuf, result, continues = node.GenerateGetRealVariables(lStateMap[node.Type], node.Addr, commStep)
	//					if result == false {
	//						setting.ZAPS.Errorf("%v:GetRealVariables fail", slaveName)
	//						commState = CommunicationState_Stop
	//					} else {
	//						commState = CommunicationState_Send
	//						commStep++
	//					}
	//				} else {
	//					txBuf, result, continues = node.DeviceCustomCmd(lStateMap[node.Type], node.Addr,
	//						cmd.FunName,
	//						cmd.FunPara,
	//						commStep)
	//					if result == false {
	//						setting.ZAPS.Errorf("%v:DeviceCustomCmd fail", slaveName)
	//						commState = CommunicationState_Stop
	//					} else {
	//						commState = CommunicationState_Send
	//						commStep++
	//					}
	//				}
	//			}
	//		case CommunicationState_Send:
	//			{
	//				//---------------发送-------------------------
	//				commInterface.WriteData(txBuf)
	//				node.CommTotalCnt++
	//				setting.ZAPS.Infof("采集接口[%s]发送数据[%d:%X]", slaveName, len(txBuf), txBuf)
	//				c.CommunicationManageMessageAdd(slaveName, "send", txBuf)
	//				commState = CommunicationState_Wait
	//			}
	//		case CommunicationState_Wait:
	//			{
	//				//阻塞读
	//				rxBuf := make([]byte, 256)
	//				rxTotalBuf := make([]byte, 0)
	//				rxBufCnt := 0
	//				rxTotalBufCnt := 0
	//				var timeout int
	//				timeout, _ = strconv.Atoi(commInterface.GetTimeOut())
	//				timerOut := time.NewTimer(time.Duration(timeout) * time.Millisecond)
	//				func() {
	//					for {
	//						select {
	//						//继续接收数据
	//						case rxBuf = <-c.PacketChan:
	//							{
	//								rxBufCnt = len(rxBuf)
	//								if rxBufCnt > 0 {
	//									rxTotalBufCnt += rxBufCnt
	//									//追加接收的数据到接收缓冲区
	//									rxTotalBuf = append(rxTotalBuf, rxBuf[:rxBufCnt]...)
	//									//清除本次接收数据
	//									rxBufCnt = 0
	//									rxBuf = rxBuf[0:0]
	//								}
	//							}
	//						//是否接收超时
	//						case <-timerOut.C:
	//							{
	//								timerOut.Stop()
	//								c.CommunicationManageMessageAdd(slaveName, "receive", rxTotalBuf)
	//								setting.ZAPS.Debugf("采集接口[%s]接收超时 接收数据[%d:%X]", slaveName, len(rxTotalBuf), rxTotalBuf)
	//
	//								node.CurCommFailCnt++
	//								if node.CurCommFailCnt >= offLineCnt {
	//									node.CurCommFailCnt = 0
	//									//设备从上线变成离线
	//									if node.CommStatus == "onLine" {
	//										content := SlaveEventTemplate{
	//											Topic:    "offLine",
	//											SlaveName: slaveName,
	//											NodeName: node.Name,
	//											Content:  node.Name,
	//										}
	//										err := eventBus.Publish("offLine", content)
	//										if err != nil {
	//											setting.ZAPS.Debugf("采集接口[%s]发布节点[%s]离线消息", slaveName, node.Name)
	//										}
	//									}
	//									node.CommStatus = "offLine"
	//								}
	//								rxTotalBufCnt = 0
	//								rxTotalBuf = rxTotalBuf[0:0]
	//
	//								commState = CommunicationState_WaitFail
	//								return
	//							}
	//						//是否正确收到数据包
	//						case rxStatus := <-node.AnalysisRx(lStateMap[node.Type], node.Addr,
	//							node.Properties, rxTotalBuf, rxTotalBufCnt):
	//							{
	//								timerOut.Stop()
	//								setting.ZAPS.Infof("采集服务[%s]接收成功 接收数据[%d:%X]", slaveName, len(rxTotalBuf), rxTotalBuf)
	//
	//								rxResult.Status = rxStatus
	//								rxResult.RxBuf = rxTotalBuf
	//
	//								c.CommunicationManageMessageAdd(slaveName, "receive", rxTotalBuf)
	//
	//								//设备从离线变成上线
	//								if node.CommStatus == "offLine" {
	//									content := SlaveEventTemplate{
	//										Topic:    "onLine",
	//										SlaveName: slaveName,
	//										NodeName: node.Name,
	//										Content:  node.Name,
	//									}
	//									err := eventBus.Publish("onLine", content)
	//									if err != nil {
	//										setting.ZAPS.Debugf("采集接口[%s]发布节点[%s]上线消息", slaveName, node.Name)
	//									}
	//								}
	//
	//								if continues == false {
	//									content := SlaveEventTemplate{
	//										Topic:    "update",
	//										SlaveName: slaveName,
	//										NodeName: node.Name,
	//										Content:  node.Name,
	//									}
	//									err := eventBus.Publish("update", content)
	//									if err != nil {
	//										setting.ZAPS.Debugf("采集接口[%s]发布节点[%s]属性更新消息", slaveName, node.Name)
	//									}
	//								}
	//
	//								node.CommSuccessCnt++
	//								node.CurCommFailCnt = 0
	//								node.CommStatus = "onLine"
	//								node.LastCommRTC = time.Now().Format("2006-01-02 15:04:05")
	//
	//								rxTotalBufCnt = 0
	//								rxTotalBuf = rxTotalBuf[0:0]
	//								commState = CommunicationState_WaitSucess
	//								return
	//							}
	//						}
	//					}
	//				}()
	//			}
	//		case CommunicationState_WaitSucess:
	//			{
	//				//通信帧延时
	//				var interval int
	//				interval, _ = strconv.Atoi(commInterface.GetInterval())
	//				time.Sleep(time.Duration(interval) * time.Millisecond)
	//				commState = CommunicationState_Stop
	//			}
	//		case CommunicationState_WaitFail:
	//			{
	//				commState = CommunicationState_Stop
	//			}
	//		case CommunicationState_Stop:
	//			{
	//				tc := time.Since(startT) //计算耗时
	//				setting.ZAPS.Debugf("采集服务[%s]本次采集用时%s", slaveName, tc)
	//				if continues == true {
	//					commState = CommunicationState_Start
	//				} else {
	//					return
	//				}
	//			}
	//		}
	//	}
	//}()

	return rxResult
}

func (c *CommunicationManageTemplate) CommunicationStateMachineIoIn(cmd CommunicationCmdTemplate, slaveName string,
	commInterface commInterface.CommunicationInterface, node *DeviceInfoTemplate,
	eventBus *eventBus.Bus, lStateMap map[string]*lua.LState, offLineCnt int) CommunicationRxTemplate {

	rxResult := CommunicationRxTemplate{
		Status: false,
	}
	//
	//txBuf := make([]byte, 0)
	//result := false
	//if cmd.FunName == "GetDeviceRealVariables" {
	//	txBuf, result, _ = node.GenerateGetRealVariables(lStateMap[node.Type], node.Addr, 0)
	//	if result == false {
	//		setting.ZAPS.Errorf("%v:GetRealVariables fail", slaveName)
	//		return rxResult
	//	}
	//} else {
	//	txBuf, result, _ = node.DeviceCustomCmd(lStateMap[node.Type], node.Addr, cmd.FunName, cmd.FunPara, 0)
	//	if result == false {
	//		setting.ZAPS.Errorf("%v:DeviceCustomCmd fail", slaveName)
	//		return rxResult
	//	}
	//}
	//commInterface.WriteData(txBuf)
	//node.CommTotalCnt++
	//
	////阻塞读
	//rxBuf := make([]byte, 1024)
	//rxBufCnt := commInterface.ReadData(rxBuf)
	//if rxBufCnt == 0 {
	//	return rxResult
	//}
	//
	//rxStatus := <-node.AnalysisRx(lStateMap[node.Type], node.Addr, node.Properties, rxBuf[:rxBufCnt], rxBufCnt)
	//if rxStatus == true {
	//	setting.ZAPS.Debugf("采集服务[%s]接收成功 接收数据[%d:%X]", slaveName, rxBufCnt, rxBuf[:rxBufCnt])
	//	//设备从离线变成上线
	//	if node.CommStatus == "offLine" {
	//		content := SlaveEventTemplate{
	//			Topic:    "onLine",
	//			SlaveName: slaveName,
	//			NodeName: node.Name,
	//			Content:  node.Name,
	//		}
	//		err := eventBus.Publish("onLine", content)
	//		if err != nil {
	//			setting.ZAPS.Debugf("采集接口[%s]发布节点[%s]上线消息", slaveName, node.Name)
	//		}
	//	}
	//
	//	node.CommSuccessCnt++
	//	node.CurCommFailCnt = 0
	//	node.CommStatus = "onLine"
	//	node.LastCommRTC = time.Now().Format("2006-01-02 15:04:05")
	//} else {
	//	node.CurCommFailCnt++
	//	if node.CurCommFailCnt >= offLineCnt {
	//		node.CurCommFailCnt = 0
	//		//设备从上线变成离线
	//		if node.CommStatus == "onLine" {
	//			content := SlaveEventTemplate{
	//				Topic:    "offLine",
	//				SlaveName: slaveName,
	//				NodeName: node.Name,
	//				Content:  node.Name,
	//			}
	//			err := eventBus.Publish("offLine", content)
	//			if err != nil {
	//				setting.ZAPS.Debugf("采集接口[%s]发布节点[%s]离线消息", slaveName, node.Name)
	//			}
	//		}
	//		node.CommStatus = "offLine"
	//	}
	//}
	//
	//rxResult.Status = rxStatus
	//rxResult.RxBuf = rxBuf

	return rxResult
}

func (c *CommunicationManageTemplate) CommunicationDirectDataStateMachine(req CommunicationDirectDataReqTemplate, commInterface commInterface.CommunicationInterface) CommunicationDirectDataAckTemplate {

	ack := CommunicationDirectDataAckTemplate{
		Status: false,
		Data:   make([]byte, 0),
	}

	commState := CommunicationState_DirectDataSend

	func() {
		for {
			switch commState {
			case CommunicationState_DirectDataSend:
				{
					//---------------发送-------------------------
					commInterface.WriteData(req.Data)
					commState = CommunicationState_DirectDataWait
				}
			case CommunicationState_DirectDataWait:
				{
					//阻塞读
					rxBuf := make([]byte, 256)
					rxTotalBuf := make([]byte, 0)
					rxBufCnt := 0
					rxTotalBufCnt := 0
					var timeout int
					timeout, _ = strconv.Atoi(commInterface.GetTimeOut())
					timerOut := time.NewTimer(time.Duration(timeout) * time.Millisecond)
					func() {
						for {
							select {
							//继续接收数据
							case rxBuf = <-c.PacketChan:
								{
									rxBufCnt = len(rxBuf)
									if rxBufCnt > 0 {
										rxTotalBufCnt += rxBufCnt
										//追加接收的数据到接收缓冲区
										rxTotalBuf = append(rxTotalBuf, rxBuf[:rxBufCnt]...)
										//清除本次接收数据
										rxBufCnt = 0
										rxBuf = rxBuf[0:0]
									}
								}
							//是否接收超时
							case <-timerOut.C:
								{
									timerOut.Stop()
									ack.Data = append(ack.Data, rxTotalBuf[:rxTotalBufCnt]...)
									if len(ack.Data) == 0 {
										ack.Status = false
									} else {
										ack.Status = true
									}
									rxTotalBufCnt = 0
									rxTotalBuf = rxTotalBuf[0:0]
									commState = CommunicationState_DirectDataStop
									return
								}
							}
						}
					}()
				}
			case CommunicationState_DirectDataStop:
				{
					return
				}
			}
		}
	}()

	return ack
}
